/*
//	CP2013 Traffic Simulator Assignment :: (MVC) Model (Function Definitions)
//	Copyright (c) 2010, Adam Rehn
//
//	This file contains the function definitions for this component.
*/
#include "model.h"

//Constructor and destructor
mvcModel::mvcModel(simulationParams setup)
{
	//Copy the setup parameters into our settings
	this->settings = setup;
	
	//Populate the roads pointer
	roads = new road*[4];
	roads[0] = &roadN;
	roads[1] = &roadS;
	roads[2] = &roadE;
	roads[3] = &roadW;
	
	//Create the vertical lanes
	{
		//Calculate common values
		lane newLane;
		newLane.w           = LANE_BASE_SIZE;
		newLane.h           = ROAD_LENGTH;
		
		//Create the Northbound Lanes
		for (int i = 0; i < settings.lanes_N; ++i)
		{
			//Northbound on North Road
			newLane.y           = 0;
			newLane.x           = ROAD_LENGTH + (LANE_BASE_SIZE * i);
			newLane.direction   = DIRECTION_NORTH;
			newLane.probability = 0;
			newLane.spawnPoint  = coordinate(0,0);
			roadN.push_back(newLane);
			
			//Northbound on South Road (have spawn point and probability)
			newLane.y           = ROAD_LENGTH + (LANE_BASE_SIZE * (setup.lanes_W + setup.lanes_E));
			newLane.probability = setup.probability_N;
			newLane.spawnPoint  = coordinate(newLane.x, newLane.y + (newLane.h - LANE_BASE_SIZE));
			roadS.push_back(newLane);
		}
		
		//Create the Southbound Lanes
		for (int i = 0; i < settings.lanes_S; ++i)
		{
			//Southbound on North Road (have spawn point and probability)
			newLane.y           = 0;
			newLane.x           = ROAD_LENGTH + (LANE_BASE_SIZE * (i + settings.lanes_N));
			newLane.direction   = DIRECTION_SOUTH;
			newLane.probability = setup.probability_S;
			newLane.spawnPoint  = coordinate(newLane.x, newLane.y);
			roadN.push_back(newLane);
			
			//Southbound on South Road
			newLane.y           = ROAD_LENGTH + (LANE_BASE_SIZE * (setup.lanes_W + setup.lanes_E));
			newLane.probability = 0;
			newLane.spawnPoint  = coordinate(0,0);
			roadS.push_back(newLane);
		}
	}
	
	//Create the horizontal lanes
	{
		//Calculate common values
		lane newLane;
		newLane.w           = ROAD_LENGTH;
		newLane.h           = LANE_BASE_SIZE;
		
		//Create the Eastbound Lanes
		for (int i = 0; i < settings.lanes_E; ++i)
		{
			//Eastbound on West Road (have spawn point and probability)
			newLane.x           = 0;
			newLane.y           = ROAD_LENGTH + (LANE_BASE_SIZE * i);
			newLane.direction   = DIRECTION_EAST;
			newLane.spawnPoint  = coordinate(newLane.x, newLane.y);
			newLane.probability = setup.probability_E;
			roadW.push_back(newLane);
			
			//Eastbound on East Road
			newLane.x           = ROAD_LENGTH + (LANE_BASE_SIZE * (setup.lanes_N + setup.lanes_S));
			newLane.probability = 0;
			newLane.spawnPoint  = coordinate(0,0);
			roadE.push_back(newLane);
		}
		
		//Create the Westbound Lanes
		for (int i = 0; i < settings.lanes_W; ++i)
		{
			//Westbound on West Road
			newLane.x           = 0;
			newLane.y           = ROAD_LENGTH + (LANE_BASE_SIZE * (i + settings.lanes_E));
			newLane.direction   = DIRECTION_WEST;
			newLane.probability = 0;
			newLane.spawnPoint  = coordinate(0,0);
			roadW.push_back(newLane);
			
			//Westbound on East Road (have spawn point and probability)
			newLane.x           = ROAD_LENGTH + (LANE_BASE_SIZE * (setup.lanes_W + setup.lanes_E));
			newLane.spawnPoint  = coordinate(newLane.x + (newLane.w - LANE_BASE_SIZE), newLane.y);
			newLane.probability = setup.probability_W;
			roadE.push_back(newLane);
		}
	}
	
	
	//Calculate the rectangle that the intersection covers
	rectangle intsctRect;
	intsctRect.x = ROAD_LENGTH;
	intsctRect.y = ROAD_LENGTH;
	intsctRect.w = (settings.lanes_N + settings.lanes_S) * LANE_BASE_SIZE;
	intsctRect.h = (settings.lanes_W + settings.lanes_E) * LANE_BASE_SIZE;
	
	//Apply the rectangle to the intersection
	this->intSct = intersection(intsctRect);
	
	//Store the rectangle for the overall simulation area
	overallSimulationArea = rectangle(0, 0, (ROAD_LENGTH*2) + intsctRect.w, (ROAD_LENGTH*2) + intsctRect.h);
	
	//AT THE MOMENT, INTERSECTION ENTRY POINTS ARE NOT YET IMPLEMENTED UNDER THE NEW SYSTEM!
}

mvcModel::~mvcModel()
{
	if (roads) delete[] roads;
}

//Use this to determine if an area is obstructed
bool mvcModel::isObstructed(rectangle& rect)
{
	//Loop through all of the vehicles and check that none of them are in the way
	for (int i = 0; i < vehicles.size(); ++i)
	{
		//Be sure to exclude boundaries, otherwise collisions will not work properly
		if (rectsOverlap(rect, vehicles[i], true))
			return true;
	}
	
	//The area is free of obstruction!
	return false;
}

//Use this to determine if a direction is supported unanimously for a given area
bool mvcModel::directionSupported(rectangle& rect, direction_t dir)
{
	//Keep track of whether or not any zones overlap or not
	bool overlap = false;
	
	//Loop through all of the zones that overlap the target rectangle
	for (int i = 0; i < zones.size(); ++i)
	{
		//Copy the pointer for easier use
		zone *currZone = zones[i];
		if (rectsOverlap(rect, *currZone, true))
		{
			//There is an overlap
			overlap = true;
			
			//If the zone does not support the direction, return false
			if (currZone->direction != dir)
				return false;
		}
	}
	
	//This ensures we return false if there were no overlaps
	return overlap;
}
